// BSD License (http://www.galagosearch.org/license)

package org.galagosearch.core.parse;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import org.galagosearch.tupleflow.Parameters;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;

/**
 * Reads data from a single text file of type HTML, XML or txt.
 * 
 * @author trevor
 */
class VersionedFileParser implements VersionedDocumentStreamParser {
    BufferedReader reader;
    String identifier;
    String xmlFileName;
    Parameters p;
    int docID;
    static String fullFile;
    public VersionedFileParser(Parameters parameters, String fileName, BufferedReader bufferedReader,int docID) {
    	this.p=parameters;
        this.identifier = getIdentifier(parameters, fileName);
        this.reader = bufferedReader;
        this.xmlFileName = fileName;
        this.docID=docID;
    }
    public VersionedFileParser(Parameters parameters, String fileName, BufferedReader bufferedReader) {
    	this.p=parameters;
        this.identifier = getIdentifier(parameters, fileName);
        this.reader = bufferedReader;
        this.xmlFileName = fileName;
    }

    public String getIdentifier(Parameters parameters, String fileName) {
        String idType = parameters.get("identifier", "filename");
        if (idType.equals("filename")) {
            return fileName;
        } else {
            String id = stripExtensions(fileName);
            id = new File(id).getName();
            return id;
        }
    }

    public String stripExtension(String name, String extension) {
        if (name.endsWith(extension)) {
            name = name.substring(0, name.length()-extension.length());
        }
        return name;
    }

    public String stripExtensions(String name) {
        name = stripExtension(name, ".gz");
        name = stripExtension(name, ".html");
        name = stripExtension(name, ".xml");
        name = stripExtension(name, ".txt");
        return name;
    }

    public String getTitle(String text) {
        int start = text.indexOf("<title>");
        if (start < 0) return "";
        int end = text.indexOf("</title>");
        if (end < 0) return "";
        return new String(text.substring(start + "<title>".length(), end));
    }
    
    public String getDocID(String text) {
        int start = text.indexOf("<id>");
        if (start < 0) return "";
        int end = text.indexOf("</id>");
        if (end < 0) return "";
        return new String(text.substring(start + "<id>".length(), end));
    }
    
    public String getTimestamp(NodeList revList,String elementName,int revNumber) throws Exception{
    	Node nNode = revList.item(revNumber);
    	Element eElement = (Element) nNode;
    	NodeList nlList = eElement.getElementsByTagName(elementName).item(0).getChildNodes();
        Node nValue = (Node) nlList.item(0);
        //System.out.println("TS: "+nValue.getNodeValue());
        return nValue.getNodeValue();
    }
    
    public String getRevisionID(NodeList revList,String elementName,int revNumber) throws Exception{
    	Node nNode = revList.item(revNumber);
    	Element eElement = (Element) nNode;
    	NodeList nlList = eElement.getElementsByTagName(elementName).item(0).getChildNodes();
        Node nValue = (Node) nlList.item(0);
        return nValue.getNodeValue();
    }
    
    /*public String getText(NodeList revList,int revNumber) throws Exception{
    	Node nNode = revList.item(revNumber);
    	return nNode.getTextContent();
    }*/
    
    public String getText(String data) throws Exception{
    	int start = data.indexOf("<revision>");
        if (start < 0) return "";
        int end = data.indexOf("</revision>");
        if (end < 0) return "";
        String dataContent = data.substring(start, end+ "</revision>".length());
        fullFile = data.substring(end + "</revision>".length(), data.length());
        //System.out.println(dataContent);
        //System.out.println("===============================================");
        return dataContent;
    }
    
    public Document getDOMParserObject(String xmlFName) throws Exception{
    	File fXmlFile = new File(xmlFName);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(fXmlFile);
		doc.getDocumentElement().normalize();
		return doc;
    }
    
    public int getNumberOfRevisions(Document documentDOM,String elementName) throws Exception{
    	NodeList nList = documentDOM.getElementsByTagName(elementName);
    	return nList.getLength();
    }
    
    public NodeList getNodeList(Document documentDOM,String elementName) throws Exception{
    	return documentDOM.getElementsByTagName(elementName);
    }
    
    public VersionedDocument[] nextDocument() throws Exception {
        if (reader == null) {
            return null;
        }
        
        StringBuilder builder = new StringBuilder();
        String line;

        while ((line = reader.readLine()) != null) {
            builder.append(line);
            builder.append("\n");
        }
       
        fullFile = builder.toString();
        String dumpDataFile = builder.toString();
        Document docDOM = getDOMParserObject(xmlFileName);
        int noOfRevisions = getNumberOfRevisions(docDOM,"revision");
        NodeList revList = getNodeList(docDOM,"revision");
        
        VersionedDocument[] result = new VersionedDocument[noOfRevisions];
   //     System.out.println("Filename: "+ xmlFileName+"\t num: "+ noOfRevisions);
        for (int revNumber = 0; revNumber < noOfRevisions; revNumber++){
		//System.out.println("Revision Number: "+revNumber);
			
        	result[revNumber] = new VersionedDocument();
        
        	result[revNumber].identifier = identifier;
        	
        	//result[revNumber].text = getText(revList,revNumber);
        	result[revNumber].text = getText(fullFile);
        	result[revNumber].metadata.put("title", getTitle(dumpDataFile));
        	result[revNumber].metadata.put("docID", getDocID(dumpDataFile));
        	result[revNumber].metadata.put("revision", getRevisionID(revList,"id",revNumber));
        	result[revNumber].metadata.put("timeBegin", getTimestamp(revList,"timestamp",revNumber));
            if(revNumber < noOfRevisions-1){
            	result[revNumber].metadata.put("timeEnd", getTimestamp(revList,"timestamp",revNumber+1));
            }
            else{
            	result[revNumber].metadata.put("timeEnd","-1");
            }
            result[revNumber].identifier=identifier+"+"+result[revNumber].metadata.get("timeBegin")+"+"+result[revNumber].metadata.get("timeEnd")+"+"+revNumber;
        }
        
        reader.close();
        reader = null;
        return result;
    }
}
